﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Proyecta.Data.Helpers
{
    /// <summary>
    /// Representa una consulta SQL. Se debe heredar la clase.
    /// </summary>
    /// <remarks>En esta clase se empleo el patron de diseno Factory Builder,
    /// dado que los metodos estaticos permiten crear objetos de forma parametrica.</remarks>
    public abstract class Query
    {
        /// <summary>
        /// Crea una condición con operador lógico AND para ser utilizada en una consulta SQL.
        /// </summary>
        /// <param name="exp1">Campo a evaluar</param>
        /// <param name="comparacion">Operador de comparación a utilizar.</param>
        /// <param name="exp2">Valor de comparación.</param>
        /// <returns>Objeto interno con los datos de la condición.</returns>
        public static QueryCondition And(string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(LogicOperator.And, exp1, comparacion, exp2);
        }

        /// <summary>
        /// Crea una condición con operador lógico AND para ser utilizada en una consulta SQL.
        /// </summary>
        /// <param name="negar">True para indicar que se usará una negación NOT.</param>
        /// <param name="exp1">Campo a evaluar</param>
        /// <param name="comparacion">Operador de comparación a utilizar.</param>
        /// <param name="exp2">Valor de comparación.</param>
        /// <returns>Objeto interno con los datos de la condición.</returns>
        public static QueryCondition And(bool negar, string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(LogicOperator.And, negar, exp1, comparacion, exp2);
        }

        /// <summary>
        /// Crea una condición con operador lógico OR para ser utilizada en una consulta SQL.
        /// </summary>
        /// <param name="exp1">Campo a evaluar</param>
        /// <param name="comparacion">Operador de comparación a utilizar.</param>
        /// <param name="exp2">Valor de comparación.</param>
        /// <returns>Objeto interno con los datos de la condición.</returns>
        public static QueryCondition Or(string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(LogicOperator.Or, exp1, comparacion, exp2);
        }

        /// <summary>
        /// Crea una condición con operador lógico OR para ser utilizada en una consulta SQL.
        /// </summary>
        /// <param name="negar">True para indicar que se usará una negación NOT.</param>
        /// <param name="exp1">Campo a evaluar</param>
        /// <param name="comparacion">Operador de comparación a utilizar.</param>
        /// <param name="exp2">Valor de comparación.</param>
        /// <returns>Objeto interno con los datos de la condición.</returns>
        public static QueryCondition Or(bool negar, string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(LogicOperator.Or, negar, exp1, comparacion, exp2);
        }

        /// <summary>
        /// Crea una condición con operador lógico AND para ser utilizada en una consulta SQL.
        /// </summary>
        /// <param name="exp1">Campo a evaluar</param>
        /// <param name="comparacion">Operador de comparación a utilizar.</param>
        /// <param name="exp2">Valor de comparación.</param>
        /// <returns>Objeto interno con los datos de la condición.</returns>
        public static QueryCondition Condition(string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(exp1, comparacion, exp2);
        }

        /// <summary>
        /// Crea una condición para ser utilizada en una consulta SQL.
        /// </summary>
        /// <param name="negar">True para indicar que se usará una negación NOT.</param>
        /// <param name="exp1">Campo a evaluar</param>
        /// <param name="comparacion">Operador de comparación a utilizar.</param>
        /// <param name="exp2">Valor de comparación.</param>
        /// <returns>Objeto interno con los datos de la condición.</returns>
        public static QueryCondition Condition(bool negar, string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(negar, exp1, comparacion, exp2);
        }

        private static QueryCondition Condition(LogicOperator operador, string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(operador, false, exp1, comparacion, exp2);
        }

        private static QueryCondition Condition(LogicOperator operador, bool negar, string exp1, CompareOperator comparacion, string exp2)
        {
            return new QueryCondition(operador, negar, exp1, comparacion, exp2);
        }

        /// <summary>
        /// Crea un nuevo objeto que contiene los datos de una columna que se desea ordenar.
        /// </summary>
        /// <param name="columna">Nombre de la columna a ordenar.</param>
        /// <param name="orden">Modo de ordenación.</param>
        /// <returns>Nuevo objeto interno con los datos de la columna a ordenar.</returns>
        public static QueryOrderedColumn OrderColumn(string columna, OrderType orden)
        {
            return new QueryOrderedColumn(columna, orden);
        }
    }
}
